package com.cityfood.controller;


import java.io.*;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.cityfood.pojo.CfOrder;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cityfood.common.pojo.OrderTradeStatus;
import com.cityfood.common.pojo.PaymentDto;
import com.cityfood.common.utils.PayUtil;
import com.cityfood.common.utils.UUIDHexGenerator;
import com.cityfood.common.utils.XmlUtil;
import com.cityfood.pojo.CfUser;

import com.cityfood.service.*;
import com.cityfood.pojo.CfOrder;
 
@Controller
public class WeiXinPaymentController{
    private final String mch_id = "1486532512";//商户号
    private final String spbill_create_ip = "47.106.118.117";//终端IP，服务器的ip
    private final String notify_url = "https://wx.hulupi.com/cityfood/weixin/paycallback";//通知地址
    private final String trade_type = "JSAPI";//交易类型
    private final String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";//统一下单API接口链接
    private final String key = "sc580Ge7hc836torj4XbxIRmeWXT7dGi"; // 商户支付密钥
    private final String appid = "wx8a66571381459ecc";

    //调试微信支付
    private static Logger logger = LoggerFactory.getLogger(WeiXinPaymentController.class);

    @Autowired
    private OrderService orderService;

    @Autowired
    private UserService userService;

    /**
     *
     * @param orderId
     * @param userId
     * @return
     * @throws UnsupportedEncodingException
     * @throws DocumentException
     */
    @RequestMapping("/weixin/payment")
    @ResponseBody
    public JSONObject payment(
    		@RequestParam(required = true) Integer orderId,
    		@RequestParam(required = true) Integer userId ) throws  DocumentException {

    	JSONObject JsonObject = new JSONObject();
        //body = new String(body.getBytes("UTF-8"),"ISO-8859-1");
        String nonce_str = UUIDHexGenerator.generate();//随机字符串
        String out_trade_no = orderService.getOrder(orderId).getOrderno();
        CfUser user = userService.getUserByUserId(userId);
        String openid = user.getOpenid();
        PaymentDto paymentPo = new PaymentDto();
        paymentPo.setAppid(appid);
        paymentPo.setMch_id(mch_id);
        paymentPo.setNonce_str(nonce_str);
        //body = new String(body.getBytes("UTF-8"),"ISO-8859-1");
        String body = "test";
        paymentPo.setBody(body);
        paymentPo.setOut_trade_no(out_trade_no);

        //String total_fee = orderService.getOrder(orderId).getTotalMoney().toString();
        String total_fee = "1";
        paymentPo.setTotal_fee(total_fee);
        paymentPo.setSpbill_create_ip(spbill_create_ip);
        paymentPo.setNotify_url(notify_url);
        paymentPo.setTrade_type(trade_type);
        paymentPo.setOpenid(openid);
        // 把请求参数打包成数组
        Map<String, Object> sParaTemp = new HashMap<>();
        sParaTemp.put("appid", paymentPo.getAppid());
        sParaTemp.put("mch_id", paymentPo.getMch_id());
        sParaTemp.put("nonce_str", paymentPo.getNonce_str());
        sParaTemp.put("body",  paymentPo.getBody());
        sParaTemp.put("out_trade_no", paymentPo.getOut_trade_no());
        sParaTemp.put("total_fee",paymentPo.getTotal_fee());
        sParaTemp.put("spbill_create_ip", paymentPo.getSpbill_create_ip());
        sParaTemp.put("notify_url",paymentPo.getNotify_url());
        sParaTemp.put("trade_type", paymentPo.getTrade_type());
        sParaTemp.put("openid", paymentPo.getOpenid());
        // 除去数组中的空值和签名参数
        Map sPara = PayUtil.paraFilter(sParaTemp);
        String prestr = PayUtil.createLinkString(sPara); // 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
        //MD5运算生成签名
        String mysign = PayUtil.sign(prestr, key, "utf-8").toUpperCase();
        paymentPo.setSign(mysign);
        //打包要发送的xml
        String respXml = XmlUtil.messageToXML(paymentPo);
        // 打印respXml发现，得到的xml中有“__”不对，应该替换成“_”
        respXml = respXml.replace("__", "_");
        String param = respXml;
        
        //String result = SendRequestForUrl.sendRequest(url, param);//发起请求
        String result = PayUtil.httpRequest(url, "POST", param);
        logger.info("请求微信预支付接口，返回 result："+result);
        // 将解析结果存储在Map中
        Map map = new HashMap();
        InputStream in=new ByteArrayInputStream(result.getBytes());
        // 读取输入流
        SAXReader reader = new SAXReader();
        Document document = reader.read(in);
        // 得到xml根元素
        Element root = document.getRootElement();
        // 得到根元素的所有子节点
        List<Element> elementList = root.elements();
        for (Element element : elementList) {
            map.put(element.getName(), element.getText());
        }
        // 返回信息
        String return_code = map.get("return_code").toString();//返回状态码
        String return_msg = map.get("return_msg").toString();//返回信息
        String result_code = map.get("result_code").toString();//返回状态码

        logger.info("请求微信预支付接口，返回 code：" + return_code);
        logger.info("请求微信预支付接口，返回 msg：" + return_msg);
        if("SUCCESS".equals(return_code) && "SUCCESS".equals(result_code)){
            // 业务结果
            String prepay_id = map.get("prepay_id").toString();//返回的预付单信息
            String nonceStr = UUIDHexGenerator.generate();
            JsonObject.put("nonceStr", nonceStr);
            JsonObject.put("package", "prepay_id=" + prepay_id);
            Long timeStamp = System.currentTimeMillis() / 1000;
            JsonObject.put("timeStamp", timeStamp + "");
            String stringSignTemp = "appId=" + appid + "&nonceStr=" + nonceStr + "&package=prepay_id=" + prepay_id + "&signType=MD5&timeStamp=" + timeStamp;
            //再次签名
            String paySign = PayUtil.sign(stringSignTemp, key, "utf-8").toUpperCase();
            JsonObject.put("paySign", paySign);
        }
        return JsonObject;
    }
 

    /**
     * 预支付时填写的 notify_url ，支付成功后的回调接口
     * @param request
     * @param response
     */
    @RequestMapping("/weixin/paycallback")
    @ResponseBody
    public void payCallback(HttpServletRequest request,HttpServletResponse response) {
        logger.info("微信回调接口方法 start");
        logger.info("微信回调接口 操作逻辑 start");
        String inputLine = "";
        String notityXml = "";
        try {
            while((inputLine = request.getReader().readLine()) != null){
                notityXml += inputLine;
            }
            //关闭流
            request.getReader().close();
            logger.info("微信回调内容信息："+notityXml);
            //解析成Map
            Map<String,String> map = PayUtil.xmlToMap(notityXml);
            //判断 支付是否成功
            if("SUCCESS".equals(map.get("result_code"))){
                logger.info("微信回调返回是否支付成功：是");
                //获得 返回的商户订单号
                String outTradeNo = map.get("out_trade_no");
                logger.info("微信回调返回商户订单号："+outTradeNo);
                //访问DB
                CfOrder payInfo = orderService.getOrder(outTradeNo);
                logger.info("微信回调 根据订单号查询订单状态："+payInfo.getTradeStatus());
                if("0".equals(payInfo.getTradeStatus().toString())){
                    //修改支付状态
                	if("1".equals(payInfo.getBuyAim().toString())){  //自购购买，进入待收货状态
                		payInfo.setTradeStatus((byte)OrderTradeStatus.WAIT_DELIVERY.getStatus());
                	}else if ("2".equals(payInfo.getBuyAim().toString())){  //送礼购买,购买后进入卡片编辑状态
                		payInfo.setTradeStatus((byte)OrderTradeStatus.CARD_EDIT.getStatus());
                	}
                    
                    //更新Bean
                    int sqlRow = orderService.updateOrderStatus(payInfo);
                    //判断 是否更新成功
                    if(sqlRow == 1){
                        logger.info("微信回调  订单号："+outTradeNo +",修改状态成功");
                        //封装 返回值
                        StringBuffer buffer = new StringBuffer();
                        buffer.append("<xml>");
                        buffer.append("<return_code>SUCCESS</return_code>");
                        buffer.append("<return_msg>OK</return_msg>");
                        buffer.append("</xml>");

                        //给微信服务器返回 成功标示 否则会一直询问 咱们服务器 是否回调成功
                        PrintWriter writer = response.getWriter();
                        //返回
                        writer.print(buffer.toString());
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
